<template>
  <div class="data-form">
    <el-form
      ref="formRef"
      :model="formData"
      :rules="formRules"
      :label-width="labelWidth"
      :label-position="labelPosition"
      :size="size"
      v-bind="$attrs"
    >
      <template v-for="field in fields" :key="field.prop">
        <el-form-item
          :label="field.label"
          :prop="field.prop"
          :required="field.required"
          :rules="field.rules"
        >
          <!-- 输入框 -->
          <el-input
            v-if="field.type === 'input'"
            v-model="formData[field.prop]"
            :placeholder="field.placeholder || `请输入${field.label}`"
            :disabled="field.disabled"
            :clearable="field.clearable !== false"
            :show-password="field.showPassword"
            :maxlength="field.maxlength"
            :rows="field.rows"
            :type="field.inputType || 'text'"
          />
          
          <!-- 文本域 -->
          <el-input
            v-else-if="field.type === 'textarea'"
            v-model="formData[field.prop]"
            type="textarea"
            :placeholder="field.placeholder || `请输入${field.label}`"
            :disabled="field.disabled"
            :rows="field.rows || 4"
            :maxlength="field.maxlength"
            :show-word-limit="field.showWordLimit"
          />
          
          <!-- 数字输入框 -->
          <el-input-number
            v-else-if="field.type === 'number'"
            v-model="formData[field.prop]"
            :placeholder="field.placeholder || `请输入${field.label}`"
            :disabled="field.disabled"
            :min="field.min"
            :max="field.max"
            :step="field.step"
            :precision="field.precision"
            :controls-position="field.controlsPosition"
            style="width: 100%"
          />
          
          <!-- 选择器 -->
          <el-select
            v-else-if="field.type === 'select'"
            v-model="formData[field.prop]"
            :placeholder="field.placeholder || `请选择${field.label}`"
            :disabled="field.disabled"
            :clearable="field.clearable !== false"
            :multiple="field.multiple"
            :filterable="field.filterable"
            style="width: 100%"
          >
            <el-option
              v-for="option in field.options"
              :key="option.value"
              :label="option.label"
              :value="option.value"
              :disabled="option.disabled"
            />
          </el-select>
          
          <!-- 单选框组 -->
          <el-radio-group
            v-else-if="field.type === 'radio'"
            v-model="formData[field.prop]"
            :disabled="field.disabled"
          >
            <el-radio
              v-for="option in field.options"
              :key="option.value"
              :label="option.value"
              :disabled="option.disabled"
            >
              {{ option.label }}
            </el-radio>
          </el-radio-group>
          
          <!-- 复选框组 -->
          <el-checkbox-group
            v-else-if="field.type === 'checkbox'"
            v-model="formData[field.prop]"
            :disabled="field.disabled"
          >
            <el-checkbox
              v-for="option in field.options"
              :key="option.value"
              :label="option.value"
              :disabled="option.disabled"
            >
              {{ option.label }}
            </el-checkbox>
          </el-checkbox-group>
          
          <!-- 开关 -->
          <el-switch
            v-else-if="field.type === 'switch'"
            v-model="formData[field.prop]"
            :disabled="field.disabled"
            :active-text="field.activeText"
            :inactive-text="field.inactiveText"
            :active-value="field.activeValue"
            :inactive-value="field.inactiveValue"
          />
          
          <!-- 日期选择器 -->
          <el-date-picker
            v-else-if="field.type === 'date'"
            v-model="formData[field.prop]"
            :type="field.dateType || 'date'"
            :placeholder="field.placeholder || `请选择${field.label}`"
            :disabled="field.disabled"
            :clearable="field.clearable !== false"
            :format="field.format"
            :value-format="field.valueFormat"
            style="width: 100%"
          />
          
          <!-- 时间选择器 -->
          <el-time-picker
            v-else-if="field.type === 'time'"
            v-model="formData[field.prop]"
            :placeholder="field.placeholder || `请选择${field.label}`"
            :disabled="field.disabled"
            :clearable="field.clearable !== false"
            :format="field.format"
            :value-format="field.valueFormat"
            style="width: 100%"
          />
          
          <!-- 文件上传 -->
          <el-upload
            v-else-if="field.type === 'upload'"
            :action="field.action"
            :headers="field.headers"
            :data="field.data"
            :name="field.name || 'file'"
            :multiple="field.multiple"
            :accept="field.accept"
            :limit="field.limit"
            :file-list="formData[field.prop] || []"
            :disabled="field.disabled"
            :auto-upload="field.autoUpload !== false"
            @success="(response, file, fileList) => handleUploadSuccess(field.prop, response, file, fileList)"
            @error="(error, file, fileList) => handleUploadError(field.prop, error, file, fileList)"
            @remove="(file, fileList) => handleUploadRemove(field.prop, file, fileList)"
          >
            <el-button type="primary">
              <el-icon><Upload /></el-icon>
              {{ field.uploadText || '点击上传' }}
            </el-button>
            <template #tip>
              <div v-if="field.tip" class="el-upload__tip">{{ field.tip }}</div>
            </template>
          </el-upload>
          
          <!-- 自定义插槽 -->
          <slot
            v-else-if="field.type === 'slot'"
            :name="field.prop"
            :field="field"
            :value="formData[field.prop]"
            :form-data="formData"
          />
        </el-form-item>
      </template>
      
      <!-- 表单按钮 -->
      <el-form-item v-if="showButtons">
        <slot name="buttons" :form-data="formData">
          <el-button @click="handleReset">重置</el-button>
          <el-button type="primary" @click="handleSubmit" :loading="submitLoading">
            {{ submitText }}
          </el-button>
        </slot>
      </el-form-item>
    </el-form>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, watch } from 'vue'
import { Upload } from '@element-plus/icons-vue'
import type { FormInstance, FormRules } from 'element-plus'

export interface FormField {
  prop: string
  label: string
  type: 'input' | 'textarea' | 'number' | 'select' | 'radio' | 'checkbox' | 'switch' | 'date' | 'time' | 'upload' | 'slot'
  placeholder?: string
  required?: boolean
  disabled?: boolean
  clearable?: boolean
  rules?: any[]
  
  // input 相关
  showPassword?: boolean
  maxlength?: number
  inputType?: string
  
  // textarea 相关
  rows?: number
  showWordLimit?: boolean
  
  // number 相关
  min?: number
  max?: number
  step?: number
  precision?: number
  controlsPosition?: 'right' | ''
  
  // select/radio/checkbox 相关
  options?: Array<{ label: string; value: any; disabled?: boolean }>
  multiple?: boolean
  filterable?: boolean
  
  // switch 相关
  activeText?: string
  inactiveText?: string
  activeValue?: any
  inactiveValue?: any
  
  // date/time 相关
  dateType?: string
  format?: string
  valueFormat?: string
  
  // upload 相关
  action?: string
  headers?: Record<string, any>
  data?: Record<string, any>
  name?: string
  accept?: string
  limit?: number
  autoUpload?: boolean
  uploadText?: string
  tip?: string
}

interface Props {
  fields: FormField[]
  modelValue?: Record<string, any>
  rules?: FormRules
  labelWidth?: string
  labelPosition?: 'left' | 'right' | 'top'
  size?: 'large' | 'default' | 'small'
  showButtons?: boolean
  submitText?: string
  submitLoading?: boolean
}

const props = withDefaults(defineProps<Props>(), {
  fields: () => [],
  modelValue: () => ({}),
  labelWidth: '120px',
  labelPosition: 'right',
  size: 'default',
  showButtons: true,
  submitText: '提交',
  submitLoading: false
})

const emit = defineEmits<{
  'update:modelValue': [value: Record<string, any>]
  submit: [formData: Record<string, any>]
  reset: []
  'upload-success': [prop: string, response: any, file: any, fileList: any[]]
  'upload-error': [prop: string, error: any, file: any, fileList: any[]]
  'upload-remove': [prop: string, file: any, fileList: any[]]
}>()

const formRef = ref<FormInstance>()
const formData = reactive<Record<string, any>>({})

// 表单规则
const formRules = computed(() => {
  const rules: FormRules = {}
  
  props.fields.forEach(field => {
    if (field.required || field.rules) {
      rules[field.prop] = []
      
      if (field.required) {
        rules[field.prop].push({
          required: true,
          message: `请${field.type === 'select' ? '选择' : '输入'}${field.label}`,
          trigger: field.type === 'select' ? 'change' : 'blur'
        })
      }
      
      if (field.rules) {
        rules[field.prop].push(...field.rules)
      }
    }
  })
  
  return { ...rules, ...props.rules }
})

// 监听 modelValue 变化
watch(() => props.modelValue, (newValue) => {
  Object.assign(formData, newValue)
}, { immediate: true, deep: true })

// 监听 formData 变化
watch(formData, (newValue) => {
  emit('update:modelValue', { ...newValue })
}, { deep: true })

// 提交表单
const handleSubmit = async () => {
  if (!formRef.value) return
  
  try {
    await formRef.value.validate()
    emit('submit', { ...formData })
  } catch (error) {
    console.error('表单验证失败:', error)
  }
}

// 重置表单
const handleReset = () => {
  if (!formRef.value) return
  
  formRef.value.resetFields()
  emit('reset')
}

// 文件上传成功
const handleUploadSuccess = (prop: string, response: any, file: any, fileList: any[]) => {
  formData[prop] = fileList
  emit('upload-success', prop, response, file, fileList)
}

// 文件上传失败
const handleUploadError = (prop: string, error: any, file: any, fileList: any[]) => {
  emit('upload-error', prop, error, file, fileList)
}

// 文件移除
const handleUploadRemove = (prop: string, file: any, fileList: any[]) => {
  formData[prop] = fileList
  emit('upload-remove', prop, file, fileList)
}

// 暴露方法
defineExpose({
  validate: () => formRef.value?.validate(),
  resetFields: () => formRef.value?.resetFields(),
  clearValidate: () => formRef.value?.clearValidate()
})
</script>

<style scoped>
.data-form {
  background: #fff;
  padding: 20px;
  border-radius: 4px;
}
</style>